home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2007 December
/
PCWKCD1207B.iso
/
Blogowanie poza sfera
/
Flock 1.0 beta
/
flock-1.0RC3.en-US.win32.exe
/
flock
/
components
/
flockFlickrService.js
< prev
next >
Wrap
Text File
|
2007-10-18
|
106KB
|
3,124 lines
// vim: ts=2 sw=2 expandtab cindent
//
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2007
// http://flock.com
//
// This file may be used under the terms of of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
function DEBUG(x) { if (ENABLE_DEBUG) debug("flockFlickrService: "+x+"\n"); }
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Components.utils.import("resource:///modules/FlockCryptoHash.jsm");
Components.utils.import("resource:///modules/FlockScheduler.jsm");
Components.utils.import("resource://gre/modules/JSON.jsm");
const FLICKR_TITLE = "Flickr Web Service";
const FLICKR_FAVICON = "chrome://flock/content/services/flickr/favicon.png";
const FLICKR_CID = Components.ID("{db720a5c-6315-49bf-a39f-b4d4aa5ed142}");
const FLICKR_CONTRACTID = "@flock.com/?photo-api-flickr;1";
const SERVICE_ENABLED_PREF = "flock.service.flickr.enabled";
const CATEGORY_COMPONENT_NAME = "Flickr JS Component"
const CATEGORY_ENTRY_NAME = "flickr"
const flockIError = Components.interfaces.flockIError;
const flockIPhotoAlbum = Components.interfaces.flockIPhotoAlbum;
const flockIPhotoPerson = Components.interfaces.flockIPhotoPerson;
const FLOCK_PHOTO_CONTRACTID = "@flock.com/photo;1";
const FLOCK_PHOTOPERSON_CONTRACTID = "@flock.com/photo-person;1";
const FLOCK_PHOTO_ALBUM_CONTRACTID = "@flock.com/photo-album;1";
const FLOCK_ERROR_CONTRACTID = "@flock.com/error;1";
const FLOCK_RDDS_CONTRACTID = "@flock.com/rich-dnd-service;1";
const PEOPLE_PROPERTIES = "chrome://flock/locale/people/people.properties";
const FLICKR_IDENTITY_URN_PREFIX = "urn:flock:identity:flickr:";
const RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
// The delay between two refreshes when the sidebar is closed (in seconds)
const FLICKR_REFRESH_INTERVAL = 3600; // 60 minutes
// The delay between two refreshes when the sidebar is open (in seconds)
const FLICKR_SHORT_INTERVAL = 3600; // 60 minutes
// The first time, only get photos not older than one week
const MEDIA_INITIAL_FETCH = 7 * 24 * 3600;
var gCompTK;
function getCompTK() {
if (!gCompTK) {
gCompTK = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
.wrappedJSObject;
}
return gCompTK;
}
var gFlickrAPI;
function Namespace(ns) { return function (arg) { return RDFS.GetResource (ns+arg); } }
const FLRDF = Namespace("http://flock.com/rdf#");
const FLICKR_STRING_BUNDLE = "chrome://flock/locale/services/flickr.properties";
// String defaults... may be updated later through Web Detective
var gStrings = {
"domains": "flickr.com,yahoo.com",
"userlogin": "http://flickr.com/signin/",
"userprofile": "http://www.flickr.com/people/%accountid%/",
"photopage": "http://www.flickr.com/photos/%accountid%/%photoid%/",
"commentsreceivedRSS": "http://api.flickr.com/services/feeds/activity.gne?id=%accountid%&format=rss_200",
"staticimage": "http://static.flickr.com/%server%/%photoid%_%secret%%size%.jpg",
"buddyicon": "http://www.flickr.com/images/buddyicon.jpg",
"staticbuddyicon": "http://static.flickr.com/%iconserver%/buddyicons/%owner%.jpg",
"nofriendavataricon": "http://static.flickr.com/0/buddyicons/%owner%.jpg",
"nomeavataricon": "http://www.flickr.com/images/buddyicon.jpg?%owner%",
"apikey": "92c2a562f0e9c2ed8dfe78f42a7734c7",
"endpoint": "http://www.flickr.com/services/rest/",
"uploadendpoint": "http://www.flickr.com/services/upload/",
"authendpoint": "http://www.flickr.com/services/auth/"
};
function flickrPhoto() {
}
flickrPhoto.prototype= {
id: "",
thumbnail: "",
webPageUrl: "",
midSizePhoto: "",
largeSizePhoto: "",
title: "",
username: "",
userid: "",
is_public: "true",
is_video: "false",
svcShortName: 'flickr',
buildTooltip: function( ) {
// do we have to use document from the window to ceate elements? -- ja
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
if (!win) return null;
var hbox = win.document.createElement('hbox');
var img = win.document.createElement('image');
img.setAttribute('src', this.icon );
hbox.appendChild(img);
var box = win.document.createElement('vbox');
box.setAttribute('style', 'max-width: 250px');
var title = win.document.createElement('label');
title.setAttribute('value', this.title );
title.setAttribute('crop', 'end');
box.appendChild(title);
var lbl = win.document.createElement('label');
lbl.setAttribute('value', this.username );
lbl.setAttribute('class', 'user');
box.appendChild(lbl);
hbox.appendChild(box)
var vbox = win.document.createElement('vbox');
var cbox = win.document.createElement('hbox');
var largeImg = win.document.createElement('image');
largeImg.setAttribute('src', this.midSizePhoto);
largeImg.setAttribute('style', 'margin-bottom: 2px;');
var spacer = win.document.createElement('spacer');
spacer.setAttribute('flex', '1');
cbox.appendChild(largeImg);
cbox.appendChild(spacer);
vbox.appendChild(cbox);
vbox.appendChild(hbox);
return vbox;
},
buildHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.midSizePhoto+'" border="0" /></a>';
},
buildLargeHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.largeSizePhoto+'" border="0" /></a>';
},
buildBBCode: function ( ) {
return '[url=' + this.webPageUrl + '][img]'+ this.largeSizePhoto +'[/img][/url]';
},
QueryInterface: function(iid) {
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.flockIPhoto)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
}
};
// ====================================================
// ========== BEGIN General helper functions ==========
// ====================================================
function loadSubScript(spec)
{
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var context = {};
loader.loadSubScript(spec, context);
return context;
}
function loadLibraryFromSpec(aSpec)
{
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript(aSpec);
}
loadSubScript("chrome://browser/content/utilityOverlay.js");
loadLibraryFromSpec("chrome://flock/content/common/flocksafe.js");
loadLibraryFromSpec("chrome://browser/content/flock/photo/photoAPI.js");
function flock_flickrBuildPhotoUrl(server, id, secret, size)
{
var convertedSize = "";
switch (size) {
case "square": convertedSize = "_s"; break;
case "thumbnail": convertedSize = "_t"; break;
case "small": convertedSize = "_m"; break;
case "medium": convertedSize = "_d"; break;
case "large": convertedSize = "_b"; break;
case "original": convertedSize = "_o"; break;
default: convertedSize = "";
}
return gStrings["staticimage"].replace("%server%", server)
.replace("%photoid%", id)
.replace("%secret%", secret)
.replace("%size%", convertedSize);
}
function _getIdentityUrn(aAccountId, aUid) {
var result = FLICKR_IDENTITY_URN_PREFIX
+ aAccountId + ":"
+ aUid;
return result;
}
function flock_flickrBuildPageUrl(aUserID, aPhotoID) {
return gStrings["photopage"].replace("%accountid%", aUserID).replace("%photoid%", aPhotoID);
}
// refresh the mediabar if it is open and contains private media
function flock_refreshMediabarIfHasPrivate() {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
// if the mediabar is open
if (win &&
win.document.getElementById("mediabar") &&
win.document.getElementById("mediabar").getAttribute("hidden") != "true" &&
win.TopbarJSCtx().gPhotoDrawer &&
win.TopbarJSCtx().gPhotoDrawer.mHasPrivateMedia)
{
win.TopbarJSCtx().gPhotoDrawer.refreshView();
}
}
// ===============================================
// ========== BEGIN flickrService class ==========
// ===============================================
function flickrService()
{
this.obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.url = "http://www.flickr.com";
this.mIsInitialized = false;
this._ctk = {
interfaces: [
"nsISupports",
"nsIClassInfo",
"nsISupportsCString",
"nsIObserver",
"flockIPollingService",
"flockIWebService",
"flockIAuthenticateNewAccount",
"flockIManageableWebService",
"flockIMediaWebService",
"flockISocialWebService",
"flockIRichContentDropHandler"
],
shortName: "flickr",
fullName: "Flickr",
description: FLICKR_TITLE,
favicon: FLICKR_FAVICON,
CID: FLICKR_CID,
contractID: FLICKR_CONTRACTID,
accountClass: flickrAccount,
needPassword: false
};
this._logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
this._logger.init('flickr');
this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
var bundle = sbs.createBundle(FLICKR_STRING_BUNDLE);
this._channels = {
"special:recent": {
title: bundle.GetStringFromName("flock.flickr.title.recent"),
supportsSearch: false
},
"special:interestingness": {
title: bundle.GetStringFromName("flock.flickr.title.interestingness"),
supportsSearch: true
}
};
this.init();
}
flickrService.prototype.serviceName = "Flickr";
flickrService.prototype.shortName = "flickr";
flickrService.prototype.handleInfoResult = function(aXML) {
var photo = aXML.getElementsByTagName("photo")[0];
var owner = aXML.getElementsByTagName("owner")[0];
var visibility = aXML.getElementsByTagName("visibility")[0];
var title = aXML.getElementsByTagName("title")[0].firstChild.nodeValue;
var dates = aXML.getElementsByTagName("dates")[0];
var id = photo.getAttribute("id");
var server = photo.getAttribute("server");
var secret = photo.getAttribute("secret");
var lastUpdate = dates.lastupdate;
var uploadDate = dates.posted;
var square_url = flock_flickrBuildPhotoUrl(server,id,secret,'square');
var small_url = flock_flickrBuildPhotoUrl(server,id,secret,'small');
var med_url = flock_flickrBuildPhotoUrl(server,id,secret,'medium');
var page_url = flock_flickrBuildPageUrl(owner.getAttribute('nsid'),id);
var icon_server = photo.getAttribute("iconserver");
var newPhoto = new flickrPhoto();
newPhoto.webPageUrl = page_url;
newPhoto.thumbnail = square_url;
newPhoto.midSizePhoto = small_url;
newPhoto.largeSizePhoto = med_url;
newPhoto.username = owner.getAttribute('username');
newPhoto.title = title;
newPhoto.id = id;
newPhoto.lastUpdate = lastUpdate;
newPhoto.uploadDate = parseInt(uploadDate)*1000;
if (icon_server == '1') {
newPhoto.icon = gStrings["buddyicon"];
}
else {
newPhoto.icon = gStrings["staticbuddyicon"]
.replace("%iconserver%", icon_server)
.replace("%owner%", owner);
}
var ispublic = visibility.getAttribute("ispublic");
if (ispublic =="1") ispublic = "true";
else ispublic = "false";
newPhoto.is_public = ispublic;
newPhoto.is_video = false;
return newPhoto;
}
flickrService.prototype.handlePhotosResult =
function (aXML, aUserid)
{
var rval = [];
var photoList = aXML.getElementsByTagName("photo");
for (var i = 0; i < photoList.length; i++) {
var photo = photoList[i];
var id = photo.getAttribute("id");
var server = photo.getAttribute("server");
var secret = photo.getAttribute("secret");
var title = photo.getAttribute("title");
var owner = photo.getAttribute("owner");
if (!owner) owner = aUserid;
var owner_name = photo.getAttribute("ownername");
var date_upload = photo.getAttribute("dateupload");
var date_added = photo.getAttribute("dateadded");
var icon_server = photo.getAttribute("iconserver");
var square_url = flock_flickrBuildPhotoUrl(server,id,secret,'square');
var small_url = flock_flickrBuildPhotoUrl(server,id,secret,'small');
var med_url = flock_flickrBuildPhotoUrl(server,id,secret,'medium');
var page_url = flock_flickrBuildPageUrl(owner,id);
var newPhoto = new flickrPhoto();
newPhoto.webPageUrl = page_url;
newPhoto.thumbnail = square_url;
newPhoto.midSizePhoto = small_url;
newPhoto.largeSizePhoto = med_url;
newPhoto.username = owner_name;
newPhoto.userid = owner;
newPhoto.title = title;
newPhoto.id = id;
if (icon_server == '1') {
newPhoto.icon = gStrings["buddyicon"];
}
else {
newPhoto.icon = gStrings["staticbuddyicon"]
.replace("%iconserver%", icon_server)
.replace("%owner%", owner);
}
newPhoto.uploadDate = parseInt((date_added) ? date_added : date_upload)*1000;
// if the photo result set doesn't return back the ispublic
// attribute, we assume that the server is returning only
// public photos back in the response
if (photo.hasAttribute("ispublic")) {
var ispublic = photo.getAttribute("ispublic");
if (ispublic =="1") ispublic = "true";
else ispublic = "false";
} else {
ispublic = "true";
}
newPhoto.is_public = ispublic;
newPhoto.is_video = false;
rval.push(newPhoto);
}
return rval;
}
flickrService.prototype.getPhotoFromRDFNode =
function (aRDFId)
{
var newPhoto = new flickrPhoto();
var coopPhoto = this.faves_coop.get(aRDFId);
newPhoto.webPageUrl = coopPhoto.URL;
newPhoto.thumbnail = coopPhoto.thumbnail;
newPhoto.midSizePhoto = coopPhoto.midSizePhoto;
newPhoto.largeSizePhoto = coopPhoto.largeSizePhoto;
newPhoto.username = coopPhoto.username;
newPhoto.userid = coopPhoto.userid;
newPhoto.title = coopPhoto.name;
newPhoto.id = coopPhoto.photoid;
newPhoto.icon = coopPhoto.favicon;
newPhoto.uploadDate = coopPhoto.datevalue;
newPhoto.is_public = coopPhoto.is_public;
newPhoto.is_video = coopPhoto.is_video;
return newPhoto;
}
flickrService.prototype.handleContactsResult =
function (aXML)
{
var rval = [];
var contactList = aXML.getElementsByTagName("contact");
for (var i = 0; i < contactList.length; i++) {
var contact = contactList[i];
var nsid = contact.getAttribute("nsid");
var username = contact.getAttribute("username");
var fullname = contact.getAttribute("fullname");
var family = contact.getAttribute("family");
var friend = contact.getAttribute("friend");
var icon_server = contact.getAttribute("iconserver");
if (true || family == "1" || friend == "1") {
this._logger.debug(".handleContactsResult(): id=" + nsid
+ " username=" + username
+ " family=" + family
+ " friend=" + friend);
var newContact = {};
newContact.id = nsid;
newContact.username = username;
newContact.fullname = username;
// If friend has no avatar, set it to null here and people sidebar
// code will fill it with the standard Flock no avatar image.
var noAvatarUrl = gStrings["nofriendavataricon"].replace("%owner%", nsid);
var avatarUrl = gStrings["staticbuddyicon"]
.replace("%iconserver%", icon_server)
.replace("%owner%", nsid);
if (noAvatarUrl == avatarUrl) {
newContact.avatarUrl = null;
} else {
newContact.avatarUrl = avatarUrl;
}
rval[nsid] = newContact;
}
}
return rval;
}
flickrService.prototype.handleAlbumsResult =
function (aXML)
{
var rval = [];
var photosetList = aXML.getElementsByTagName("photoset");
var titleList = aXML.getElementsByTagName("title");
for (var i = 0; i < photosetList.length; i++) {
var id = photosetList[i].getAttribute("id");
var title = titleList[i].firstChild.nodeValue;
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(flockIPhotoAlbum);
newAlbum.id = id;
newAlbum.title = title;
rval.push(newAlbum);
}
return rval;
}
flickrService.prototype.getContacts =
function flickrService_getContacts(aListener)
{
this._logger.info(".getContacts(...)");
var inst = this;
var myListener = {
onResult: function (aXML) {
var peeps = inst.handleContactsResult(aXML);
var result = {
wrappedJS: peeps
}
aListener.onGetContactsResult(result);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.contacts.getList", dict);
}
flickrService.prototype.getPhoto =
function (aListener, aID)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var photo = inst.handleInfoResult(aXML);
aListener.onGetPhoto(photo);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
params.photo_id = aID;
var dict = params2Dictionary(params);
if (this.getAuthUser()) {
this.authenticatedCall(myListener, "flickr.photos.getInfo", dict);
} else {
this.call(myListener, "flickr.photos.getInfo", dict);
}
}
flickrService.prototype.createAlbum =
function (aListener, aTitle)
{
// trim white space from front and end of string
aTitle = aTitle.replace(/^\s+|\s+$/g, "");
if (aTitle) {
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(flockIPhotoAlbum);
newAlbum.title = aTitle;
var date = new Date(); //hopefully this won't collide with an actual id!
newAlbum.id = date.getTime();
this.api.fakeAlbums[newAlbum.id] = newAlbum;
aListener.onCreateAlbum(newAlbum);
} else {
var error = Components.classes[FLOCK_ERROR_CONTRACTID].createInstance(flockIError);
error.errorCode = error.PHOTOSERVICE_EMPTY_ALBUMNAME;
aListener.onError(error);
}
}
flickrService.prototype.getAlbums =
function flickrService_getAlbums(aListener, aUsername)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
try {
var rval = inst.handleAlbumsResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onGetAlbumsResult(enum_);
} catch(e) {
aListener.onError(null);
}
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
if (aUsername) {
params.user_id = aUsername;
}
var dict = params2Dictionary(params);
if (this.getAuthUser()) {
this.authenticatedCall(myListener, "flickr.photosets.getList", dict);
} else {
this.call(myListener, "flickr.photosets.getList", dict);
}
}
flickrService.prototype.getAccountStatus =
function flickrService_getAccountStatus(aListener)
{
var inst = this;
var myListener = {
onResult:function (aXML) {
try {
inst._logger.info('we got a result for account status...');
var result = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
var username = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
var bandwidth = aXML.getElementsByTagName('bandwidth')[0];
var maxFileSize = aXML.getElementsByTagName('filesize')[0];
var isPro = aXML.getElementsByTagName('user')[0].getAttribute('ispro');
var maxSpace = bandwidth.getAttribute("max");
var usedSpace = bandwidth.getAttribute("used");
result.setPropertyAsAString("username", username);
result.setPropertyAsAString("maxSpace", maxSpace);
result.setPropertyAsAString("usedSpace", usedSpace);
result.setPropertyAsAString("maxFileSize", maxFileSize);
result.setPropertyAsAString("usageUnits", "bytes");
result.setPropertyAsBool("isPremium", (isPro == "1"));
aListener.onSuccess(result, "");
} catch (ex) {
inst._logger.info('getaccountstatus error >>>>>>>>>>>>>>>>>>>>' + ex);
}
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.people.getUploadStatus", dict);
}
flickrService.prototype.getContactsPhotos =
function flickrService_getContactsPhotos(aListener)
{
// return; // XXX TODO FIXME (JMC): Save me from contacts' photos hanging my browser!
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aXML) {
aListener.onError(null);
}
}
var params = {};
params.single_photo = "1";
params.include_self = "1";
params.extras = "owner_name,license,date_upload,icon_server";
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.photos.getContactsPhotos", dict);
}
flickrService.prototype.getMostRecentPhotoForList =
function flickrService_getMostRecentPhotoForList(aListener, aEnumerator)
{
var mg = new MultiGetter();
mg.init(this, aListener, aEnumerator);
}
flickrService.prototype.findByUsername =
function flickrService_findByUsername(aListener, aUsername)
{
var inst = this;
var userListener = function(aListener) {
this.mListener = aListener;
}
userListener.prototype.onGetInfo = function (aPerson) {
this.mListener.onFindByUsernameResult(aPerson);
}
userListener.prototype.onError = function (aError) {
inst._logger.info(aError);
this.mListener.onError(aError);
}
var myListener = {
onResult: function (aXML) {
var user = aXML.getElementsByTagName("user")[0];
var id = user.getAttribute("id");
inst.people_getInfo(new userListener(aListener), id);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.username = aUsername;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.people.findByUsername", dict);
}
flickrService.prototype.lookupUser =
function (aListener, aURL)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
.createInstance(flockIPhotoPerson);
var user = aXML.getElementsByTagName("user")[0];
newUserObj.service = inst;
newUserObj.id = user.getAttribute("id");
newUserObj.username = user.getElementsByTagName("username")[0].childNodes[0].nodeValue;
newUserObj.fullname = newUserObj.username;
aListener.onLookupUser(newUserObj);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.url = aURL;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.urls.lookupUser", dict);
}
flickrService.prototype.people_getInfo =
function (aListener, aUserId)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID].createInstance(flockIPhotoPerson);
var person = aXML.getElementsByTagName("person")[0];
var icon_server = person.getAttribute("iconserver");
var count = person.getElementsByTagName("photos")[0].getElementsByTagName("count")[0].firstChild.nodeValue;
newUserObj.service = inst;
newUserObj.id = person.getAttribute("id");
newUserObj.username = person.getElementsByTagName('username')[0].firstChild.nodeValue + '';
newUserObj.fullname = newUserObj.username;
newUserObj.avatarUrl = gStrings["staticbuddyicon"]
.replace("%iconserver%", icon_server)
.replace("%owner%", newUserObj.id);
newUserObj.photoCount = parseInt(count);
aListener.onGetInfo(newUserObj);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.user_id = aUserId;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.people.getInfo", dict);
}
flickrService.prototype.queryChannel =
function flickrService_queryChannel(aListener, aQueryString, aCount, aPage)
{
var aQuery = new queryHelper(aQueryString);
// return; // XXX TODO FIXME: This is killing performance!
var inst=this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {
per_page: aCount,
page: aPage,
extras: "owner_name,icon_server,date_upload,license"
};
if (aQuery.getKey('special') == 'recent') {
if (aQuery.hasKey('search')) {
params.text = aQuery.getKey('search');
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.getRecent", dict)
}
}
if (aQuery.getKey("special") == 'interestingness') {
if (aQuery.hasKey('search')) {
params.text = aQuery.getKey('search');
params.sort = 'interestingness-desc';
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.interestingness.getList", dict)
}
}
if (aQuery.hasKey('search')) {
aText = aQuery.getKey('search');
if (aText && aText.length) {
params.text = aText;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
}
}
}
flickrService.prototype.poolSearch =
function flickrService_poolSearch(aListener, aQueryString, aCount, aPage)
{
var aQuery = new queryHelper(aQueryString);
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
/*
var aText;
if (aQuery.split('?').length > 1) {
aText = aQuery.split('?')[1];
aQuery = aQuery.split('?')[0];
}
aQuery = aQuery.split(':')[1]
*/
var params = {
group_id: aQuery.pool,
per_page: aCount,
page: aPage,
extras: "owner_name,icon_server,date_upload,license"
};
if (aQuery.search) {
params.tags = aQuery.search;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.groups.pools.getPhotos", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.groups.pools.getPhotos", dict)
}
}
flickrService.prototype.search =
function flickrService_search(aListener, aQueryString, aCount, aPage)
{
var aQuery = new queryHelper(aQueryString);
if (aQuery.pool) {
this.poolSearch(aListener, aQueryString, aCount, aPage);
return;
}
if (!aQuery.user) {
this.queryChannel(aListener, aQueryString, aCount, aPage);
return;
}
var aUserid = aQuery.user;
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML, aUserid);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
// Flickr return the photo in the reverse side when calling flickr.photosets.getPhotos!
// So we need to enumerate backward :-/
var myPhotosetListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML, aUserid);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.pop();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
if (aUserid && aUserid.length) params.user_id = aUserid;
params.per_page = aCount;
params.page = aPage;
if (aQuery.search) params.text = aQuery.search;
params.tag_mode = "all";
params.extras = "owner_name,license,date_upload,icon_server";
if (aQuery.album) {
params.photoset_id = aQuery.album;
}
var dict = params2Dictionary(params);
if (params.photoset_id) {
if (aPage > 1) return; // this is because the flickr call doesn't support pagination [bug 4770]
dict = params2Dictionary(params);
if (this.getAuthUser())
this.authenticatedCall(myPhotosetListener, "flickr.photosets.getPhotos", dict);
else
this.call(myPhotosetListener, "flickr.photosets.getPhotos", dict);
} else if (params.user_id || params.text) {
if (this.getAuthPerson()) {
this.authenticatedCall(myListener, "flickr.photos.search", dict);
}
else {
this.call(myListener, "flickr.photos.search", dict);
}
}
}
flickrService.prototype.supportsSearch =
function flickrService_supportsSearch( aQueryString ) {
var aQuery = new queryHelper(aQueryString);
if (aQuery.special) {
var channel = this._channels["special:" + aQuery.special];
if (channel) {
return channel.supportsSearch;
}
}
if (aQuery.album) {
return false;
}
if (aQuery.user) {
return true;
}
if (aQuery.search) {
return false;
}
return false;
}
flickrService.prototype.mSupportsTitle = true;
flickrService.prototype.mSupportsTags = true;
flickrService.prototype.mSupportsContacts = true;
flickrService.prototype.mSupportsPrivacy = true;
flickrService.prototype.supportsFeature =
function flickrService_supportsFeature(aFeature)
{
var supports = {};
supports.tags = true;
supports.title = true;
supports.fileName = false;
supports.contacts = true;
supports.privacy = true;
supports.albumCreation = true;
return (supports[aFeature] == true);
}
flickrService.prototype.init =
function flickrService_init()
{
// Prevent re-entry
if (this.mIsInitialized) return;
this.mIsInitialized = true;
this._logger.info(".init()");
var evtID = this._profiler.profileEventStart("flickr-init");
// Determine whether this service has been disabled, and unregister if so.
this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
!this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
{
this._logger.info("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
catMgr.deleteCategoryEntry("flockMediaProvider", CATEGORY_ENTRY_NAME, true);
return;
}
if (!gFlickrAPI) {
gFlickrAPI = new FlickrAPI();
}
this.api = gFlickrAPI;
this.api.svc = this;
var inst = this;
this.faves_coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
this.urn = "urn:flickr:service";
this.svcCoopObj = new this.faves_coop.Service(
this.urn,
{
name: "flickr",
desc: "The Flickr Service",
contactLabel: 'Contacts'
}
);
this.svcCoopObj.serviceId = FLICKR_CONTRACTID;
// Load Web Detective file
this.webDetective = this.acUtils.useWebDetective("flickr.xml");
for (var s in gStrings) {
gStrings[s] = this.webDetective.getString("flickr", s, gStrings[s]);
}
this.svcCoopObj.domains = gStrings["domains"];
this.svcCoopObj.loginURL = gStrings["userlogin"];
// Update auth states
try {
if (this.webDetective.detectCookies("flickr", "loggedout", null)) {
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
this.api.logout();
}
} catch (ex) {
this._logger.error("ERROR updating auth states for Flickr: "+ex);
}
// On browser restart if a Flickr coop account is still marked as
// authenticated we also need to reauth the api. We do this by calling
// login() on the xpcom account obj. However, we have to wait while
// the Flickr service is finished constructing itself.
var reloginCallback = {
notify: function reloginCallback_notify(aTimer) {
inst._logger.info("reloginCallback.notify()")
var acctURN = inst.acUtils
.getFirstAuthenticatedAccountForService(inst.svcCoopObj
.serviceId);
if (acctURN) {
var account = inst.getAccount(acctURN);
if (account) {
var reloginListener = {
onSuccess: function reloginListener_onSuccess(aSubject, aTopic) {
inst._logger.info(".init(): reloginListener: onSuccess()");
},
onError: function reloginListener_onError(aError) {
inst._logger.info(".init(): reloginListener: onError()");
inst.faves_coop.get(acctURN).isAuthenticated = false;
}
};
account.login(reloginListener);
}
}
}
};
var reloginTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
reloginTimer.initWithCallback(reloginCallback, 100, Ci.nsITimer.TYPE_ONE_SHOT);
var timerFunc = {
inProgress: false,
count: 0,
observe: function(subject, topic, state) {
//if (topic == 'nsPref:changed' && state == FLICKR_TOKEN_PREF_ID) {
// var oldToken = flock_getCharPref(FLICKR_TOKEN_PREF_ID);
// if (oldToken && oldToken.length && !inst.api.isLoggedIn()) {
// this.inProgress = true;
// inst.api.checkToken(this, oldToken);
// }
//}
},
notify: function(aTimer) {
if (this.inProgress) return;
if (inst.api.isLoggedIn()) {
inst.api.processPendingUploadTickets();
inst.api.processPendingAlbumAdditions();
}
},
onResult: function(aXML) {
this.inProgress = false;
},
onSuccess: function(aXML) {
this.inProgress = false;
},
onError: function(aError) {
inst.logout();
this.inProgress = false;
}
}
//timerFunc.observe(null, 'nsPref:changed', FLICKR_TOKEN_PREF_ID);
timerFunc.notify();
//var prefs = Components.classes['@mozilla.org/preferences-service;1']
// .getService(Components.interfaces.nsIPrefBranch2);
//prefs.addObserver(FLICKR_TOKEN_PREF_ID, timerFunc, false);
timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(timerFunc, 5 * 1 * 1000, 1); //re-check token
this._profiler.profileEventEnd(evtID, "");
}
flickrService.prototype.__defineGetter__('supportsTitle', function () { return this.mSupportsTitle; })
flickrService.prototype.__defineGetter__('supportsTags', function () { return this.mSupportsTags; })
flickrService.prototype.__defineGetter__('supportsContacts', function () { return this.mSupportsContacts; })
flickrService.prototype.__defineGetter__('supportsPrivacy', function () { return this.mSupportsPrivacy; })
flickrService.prototype.getAuthState =
function flickrService_getAuthState()
{
return this.state;
}
flickrService.prototype.__defineGetter__('authState', function () { return this.state; })
flickrService.prototype.logout =
function flickrService_logout()
{
this.api.logout();
this.acUtils.removeCookies(this.webDetective.getSessionCookies("flickr"));
}
flickrService.prototype.getAuthUser = function () {
return this.api.getAuthUser();
}
flickrService.prototype.getAuthPerson = function () {
var user = this.api.getAuthUser();
if (!user) {
return null;
}
var person = {};
person.id = user.id;
person.fullname = user.fullname;
person.username = user.username;
person.service = this;
return person;
}
flickrService.prototype.__defineGetter__('isUploading', function () { return this.running; })
flickrService.prototype.dictionary2Params =
function flickrService_dictionary2Params(aDictionary)
{
var params = {};
var obj = {};
var count = {};
var keys = aDictionary.getKeys(count, obj);
for (var i = 0; i < keys.length;++i) {
var supports = aDictionary.getValue(keys[i]);
var supportsString = supports.QueryInterface(Components.interfaces.nsISupportsString);
var val = supportsString.toString();
params[keys[i]] = val;
}
return params;
}
flickrService.prototype.call =
function flickrService_call(aListener, aMethod, aDictionary)
{
var params = this.dictionary2Params(aDictionary);
this.api.call(aListener, aMethod, params);
}
flickrService.prototype.authenticatedCall =
function flickrService_authenticatedCall(aListener, aMethod, aDictionary)
{
if (!this.getAuthPerson()) {
throw "not logged in";
}
var params = this.dictionary2Params(aDictionary);
this.api.authenticatedCall(aListener, aMethod, params);
}
flickrService.prototype.upload =
function flickrService_upload(aListener, aUpload, aFile)
{
var params = {};
params.title = aUpload.title;
params.description = aUpload.description;
params.is_family = aUpload.is_family;
params.is_friend = aUpload.is_friend;
params.is_public = aUpload.is_public;
params.async = "1";
params.tags = aUpload.tags;
this.api.upload(aListener, aFile, params, aUpload);
}
flickrService.prototype.cancelUpload =
function flickrService_cancelUpload()
{
try { this.api.uploader.req.abort(); }
catch(e){};
}
flickrService.prototype.addCoopPerson =
function flickrService_addCoopPerson(aPhotoPerson, aCoopAccount) {
var person = aPhotoPerson;
// We include the current accountId in the identity urn to prevent friend
// collisions if multiple Facebook accounts have the same friend.
var identityUrn = _getIdentityUrn(aCoopAccount.accountId,
person.id);
var updating = this.faves_coop.Identity.exists(identityUrn);
var identity;
if (updating) {
identity = this.faves_coop.get(identityUrn);
if (this._personUpdateRequired (aCoopAccount,person)) {
// update data of the identity coop obj here
identity.name = person.username;
identity.avatar = person.avatarUrl;
}
} else {
identity = new this.faves_coop.Identity(
identityUrn,
{
name: person.username,
serviceId: FLICKR_CONTRACTID,
accountId: person.id,
avatar: person.avatarUrl,
statusMessage: '',
lastUpdate: 0,
lastUpdateType: "media"
}
);
aCoopAccount.friendsList.children.add(identity);
}
if (person.media) {
this._incrementMedia(person.id, person.media.count, person.media.latest);
}
}
flickrService.prototype._incrementMedia =
function flickrService__incrementMedia(aUid, aCount, aLatest) {
this._logger.info("._incrementMedia('" + aUid + "')");
var currAcctURN = this.acUtils
.getFirstAuthenticatedAccountForService(FLICKR_CONTRACTID);
var currAcct = this.faves_coop.get(currAcctURN);
// Update the count on the identity...
var identityUrn = _getIdentityUrn(currAcct.accountId, aUid);
identity = this.faves_coop.get(identityUrn);
if (!identity.lastUpdate) {
identity.lastUpdate = aLatest;
var lastweek = parseInt(Date.now() / 1000) - MEDIA_INITIAL_FETCH;
// Friend uploaded pictures in the last week!
if (aLatest > lastweek) {
identity.unseenMedia += aCount;
}
} else if (aLatest > identity.lastUpdate) {
identity.unseenMedia += aCount;
identity.lastUpdate = aLatest;
}
}
flickrService.prototype._personUpdateRequired =
function flickrService__personUpdateRequired(aCoopPerson, aPerson) {
return (aCoopPerson.name != aPerson.fullname)
|| (aCoopPerson.avatar != aPerson.pic_square);
}
flickrService.prototype._updateUserCommentCount =
function flickrService__updateUserCommentCount(aCoopAccount)
{
this._logger.info("._updateUserCommentCount('" + aCoopAccount.id() + "')");
var timespanMS = 0;
if (!aCoopAccount.lastUpdateDate) {
// First time refreshing this account, so notify on all photo comments for
// the past week.
aCoopAccount.lastUpdateDate = new Date();
var lastweek = aCoopAccount.lastUpdateDate.getTime()
- (MEDIA_INITIAL_FETCH * 1000);
timespanMS = aCoopAccount.lastUpdateDate.getTime() - lastweek;
aCoopAccount.flickr_comments = 0;
aCoopAccount.flickr_comments_timespan = 0;
} else {
var today = new Date();
timespanMS = today.getTime() - aCoopAccount.lastUpdateDate.getTime();
}
// This controls the time span (in hours) that photo comments will be shown
// for when the user chooses to view comment noties.
var timespanHrs = timespanMS / (60 * 60 * 1000);
aCoopAccount.flickr_comments_timespan += timespanHrs;
var api_key = this.api_key;
var params = {
api_key: api_key,
timeframe: timespanHrs + "h",
};
var inst = this;
var commentListener = {
onResult: function commentListener_onResult(aXML) {
var items = aXML.getElementsByTagName("item");
if (aCoopAccount.flickr_comments < items.length) {
inst._lightPeopleIcon();
}
// Add the flickr_comment count from previous check
aCoopAccount.flickr_comments += items.length;
},
onError: function commentListener_onError(aXML) {
}
};
var dict = params2Dictionary(params);
this.authenticatedCall(commentListener, "flickr.activity.userPhotos", dict);
}
flickrService.prototype._updateUserAccount =
function flickrService__updateUserAccount(aCoopAccount)
{
this._logger.info("._updateUserAccount('" + aCoopAccount.id() + "')");
var inst = this;
var hr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
hr.onreadystatechange = function updateAccount_onreadystatechange(aEvent) {
if (hr.readyState == 4) {
var results = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
if (inst.webDetective.detectNoDOM("flickr", "accountinfo", "",
hr.responseText, results))
{
inst._updateUserStatusFromResults(aCoopAccount, results);
inst._updateUserCommentCount(aCoopAccount);
}
}
}
hr.open("GET", this.webDetective.getString("flickr", "scrapeAccountInfo",
"http://www.flickr.com/"));
hr.send(null);
}
flickrService.prototype._lightPeopleIcon =
function flickrService__lightPeopleIcon()
{
this._logger.debug("._lightPeopleIcon()");
this.obs.notifyObservers(null, "new-people-notification", null);
}
flickrService.prototype._updateUserStatusFromResults =
function flickrService__updateUserAccount(aCoopAccount, aResults)
{
this._logger.info("._updateUserStatusFromResults('" + aCoopAccount.id() + "')");
var username = aResults.getPropertyAsAString("username");
if (username && username.length) {
aCoopAccount.name = username;
}
var avatarURL = aResults.getPropertyAsAString("avatarURL");
if (avatarURL && avatarURL.length) {
// If user account has no avatar, set it to null here and people sidebar
// code will fill it with the standard Flock no avatar image.
var accountid = aResults.getPropertyAsAString("accountid");
var noAvatarUrl = gStrings["nomeavataricon"].replace("%owner%", accountid);
if (noAvatarUrl == avatarURL) {
aCoopAccount.avatar = null;
} else {
aCoopAccount.avatar = avatarURL;
}
}
var messages = aResults.getPropertyAsAString("messages");
if (messages && messages.length) {
if (aCoopAccount.accountMessages < messages) {
this._lightPeopleIcon();
}
aCoopAccount.accountMessages = messages;
} else {
aCoopAccount.accountMessages = 0;
}
}
// BEGIN flockIPollingService
flickrService.prototype.refresh =
function flickrService_refresh(aURN, aListener)
{
this._logger.info("{flockIPollingService}.refresh('"+aURN+"', ...)");
var refreshItem = this.faves_coop.get(aURN);
var inst = this;
if (refreshItem instanceof this.faves_coop.Account) {
var peopleHash;
if (!this.api.isLoggedIn()) {
this._logger.debug("api is not logged in - skipping refresh");
aListener.onResult();
return;
}
var recentPhotosListener = {
onResult: function recentPhotosListener_onResult(aXML) {
var photosList = aXML.getElementsByTagName("photo");
for (var i = 0; i < photosList.length; i++) {
var photo = photosList[i];
var personId = photo.getAttribute("owner");
var latest = photo.getAttribute("dateupload");
// Add media info to people hash
peopleHash[personId].media = {
count: 1,
latest: latest
};
}
// Now that we have all we need, update the RDF
function myWorker(aShouldYield) {
// ADD or update existing people
for (var uid in peopleHash) {
inst.addCoopPerson(peopleHash[uid], refreshItem);
if (aShouldYield()) {
yield;
}
}
// REMOVE locally people removed on the server
var localEnum = refreshItem.friendsList.children.enumerate();
while (localEnum.hasMoreElements()) {
var identity = localEnum.getNext();
if (!peopleHash[identity.accountId]) {
inst._logger.info("Friend " + identity.accountId
+ " has been deleted on the server");
refreshItem.friendsList.children.remove(identity);
identity.destroy();
}
}
if (inst.acUtils.isPeopleSidebarOpen()) {
refreshItem.nextRefresh = new Date(Date.now()
+ FLICKR_SHORT_INTERVAL * 1000);
}
aListener.onResult();
} // end myWorker()
FlockScheduler.schedule(null, 0.05, 10, myWorker);
},
onError: function recentPhotosListener_onError(aXML) {
inst._logger.error("recentPhotosListener error");
}
};
this._updateUserAccount(refreshItem);
this.getContacts({
onGetContactsResult: function getContacts_onGetContactsResult(aResult) {
peopleHash = aResult.wrappedJS;
var api_key = inst.api_key;
var params = {
api_key: api_key,
single_photo: 1,
count: 50,
extras: "date_upload"
};
var dict = params2Dictionary(params);
inst.authenticatedCall(recentPhotosListener,
"flickr.photos.getContactsPhotos",
dict);
},
onError: function getContacts_onError(aError) {
aListener.onError(aError);
}
});
} else {
throw CR.NS_ERROR_ABORT;
this._logger.error("can't refresh " + aURN + " (unsupported type)");
aListener.onError(null);
}
}
// END flockIPollingService
flickrService.prototype.migrateAccount =
function flickrService_migrateAccount( aId, aUsername ) {
this.init();
var token = '';
/*
try {
token = flock_getCharPref('flock.photo.flickr.token');
} catch (e) { }
*/
this.addAccountById( aId, false, null, aUsername, token);
}
// BEGIN flockIWebService interface
flickrService.prototype.addAccountById =
function flickrService_addAccountById(aAccountID, aIsTransient, aListener, aUsername, aToken)
{
this._logger.info("{flockIWebService}.addAccountById('"+aAccountID+"', "+aIsTransient+")");
if (!aUsername) {
// Get the password associated with this account
var pw = this.acUtils.getPassword(this.urn+':'+aAccountID);
// FIX ME - name shouldn't be email address (pw.user) - ja
var name = (pw) ? pw.user : aAccountID;
var token = '';
var pollable = false;
var auth = false;
} else {
var name = aUsername;
var token = aToken;
var pollable = true;
var auth = true;
}
// Account
var accountURN = "urn:flock:flickr:account:"+aAccountID;
var account = this.faves_coop.get(accountURN);
if (!account) {
var account = new this.faves_coop.Account(accountURN, {
name: name,
accountId: aAccountID,
serviceId: FLICKR_CONTRACTID,
service: this.svcCoopObj,
favicon: FLICKR_FAVICON,
URL: gStrings["userprofile"].replace("%accountid%", aAccountID),
isTransient: aIsTransient,
isPollable: pollable,
refreshInterval: FLICKR_REFRESH_INTERVAL,
authToken: token,
isAuthenticated: auth,
accountMessages: 0
});
this.faves_coop.accounts_root.children.add(account);
}
//instansiate the friends list object
var friendsListUrn = accountURN + ":friends";
if (!account.friendsList) {
var friendsList = new this.faves_coop.FriendsList(
friendsListUrn,
{
account: account
});
account.friendsList = friendsList;
}
// Instanciate account component
var acct = this.getAccount(account.id());
if (aListener) {
aListener.onSuccess(acct, "addAccount");
}
return acct;
}
// END flockIWebService interface
// BEGIN flockIAuthenticateNewAccount interface
flickrService.prototype.authenticateNewAccount =
function flickrService_authenticateNewAccount(aListener)
{
this._logger.info("{flockIAuthenticateNewAccount}.authenticateNewAccount(aListener)");
aListener.onStart(null, "newaccountstarted");
var inst = this;
var frobListener = {
onResult: function (aXML) {
inst._logger.info(".authenticateNewAccount(): frobListener: onResult()");
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
var topWin = wm.getMostRecentWindow(null);
var frob = aXML.getElementsByTagName("frob")[0].firstChild.nodeValue;
var authURL = inst.api.getAuthUrl(frob, "write");
var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"
+ "url="+escape(authURL)+"&finalString=logout.gne";
var chrome = "chrome,close,titlebar,resizable=yes,toolbar,dialog=no,"
+ "scrollbars=yes,modal,centerscreen";
topWin.open(url, "_blank", chrome);
var acctURN = inst.acUtils.getFirstAuthenticatedAccountForService(FLICKR_CONTRACTID);
var account = null;
try {
account = inst.getAccount(acctURN);
if (!account) throw "ACCOUNT WAS NOT CREATED";
} catch (ex) {
inst._logger.info(".authenticateNewAccount(): frobListener: onResult(): ERROR: account was not created");
if (aListener) aListener.onError(ex);
}
if (aListener) aListener.onSuccess(account, "", null);
},
onError: function (aError) {
inst._logger.info(".authenticateNewAccount(): frobListener: onError()");
if (aListener) aListener.onError(aError);
}
};
this.api.call(frobListener, "flickr.auth.getFrob", null);
}
// END flockIAuthenticateNewAccount
// BEGIN flockIManageableWebService interface
flickrService.prototype.updateAccountStatusFromDocument =
function flickrService_updateAccountStatusFromDocument(aDocument)
{
this._logger.info("{flockIManageableWebService}.updateAccountStatusFromDocument()");
if (this.webDetective.detect("flickr", "loggedout", aDocument, null))
{
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
// Also de-authenticate the API
this.api.logout();
flock_refreshMediabarIfHasPrivate()
} else if (this.webDetective.detect("flickr", "loggedin", aDocument, null)) {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
if (this.webDetective.detect("flickr", "accountinfo", aDocument, results)) {
var accountID = results.getPropertyAsAString("accountid");
if (accountID && accountID.length) {
var accountURN = this.acUtils.getAccountURNById(this.urn, accountID);
var acct = this.faves_coop.get(accountURN);
if (!acct.isAuthenticated) {
var inst = this;
var loginListener = {
onSuccess: function (aSubject, aTopic) {
inst._logger.info(".updateAccountStatusFromDocument(): loginListener: onSuccess()");
},
onError: function (aError) {
inst._logger.info(".updateAccountStatusFromDocument(): loginListener: onError()");
inst._logger.info(aError ? (aError.errorString) : "No details");
acct.isAuthenticated = false;
}
};
this.getAccount(accountURN).login(loginListener);
// I'm going to somewhat prematurely assume that the authentication
// will succeed. If it fails, the listener will catch it.
acct.isAuthenticated = true;
}
}
}
}
}
// END flockIManageableWebService interface
// BEGIN flockISocialWebService interface
flickrService.prototype.markAllMediaSeen =
function flickrService_markAllMediaSeen(aIdentityUrn) {
var identity = this.faves_coop.get(aIdentityUrn);
identity.unseenMedia = 0;
}
flickrService.prototype.maxStatusLength = 0;
// END flockISocialWebService interface
// BEGIN flockIMediaWebService interface
flickrService.prototype.decorateForMedia =
function flickrService_decorateForMedia(aDocument)
{
this._logger.info("{flockIMediaWebService}.decorateForMedia(aDocument)");
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
var mediaArr = [];
if (this.webDetective.detect("flickr", "person", aDocument, results)) {
var media = {
name: results.getPropertyAsAString("username"),
query: "user:" + results.getPropertyAsAString("userid") + "|username:" + results.getPropertyAsAString("username"),
label: results.getPropertyAsAString("username"),
favicon: this.icon,
service: this.shortName
}
mediaArr.push(media);
}
if (this.webDetective.detect("flickr", "pool", aDocument, results)) {
var media = {
name: results.getPropertyAsAString("groupname"),
query: "pool:" + results.getPropertyAsAString("groupid") + "|albumlabel:" + results.getPropertyAsAString("groupname"),
label: results.getPropertyAsAString("groupname"),
favicon: this.icon,
service: this.shortName
}
mediaArr.push(media);
}
if (mediaArr.length > 0) {
if (!aDocument._flock_decorations) {
aDocument._flock_decorations = {};
}
aDocument._flock_decorations.mediaArr = mediaArr;
this.obs.notifyObservers(aDocument, "media", "media:update");
}
}
flickrService.prototype.handlesMediaStream =
function flickrService_handlesMediaStream()
{
return true;
}
flickrService.prototype.checkIsStreamUrl =
function flickrService_checkIsStreamUrl(aUrl)
{
if (this.webDetective.detectNoDOM("flickr", "isStreamUrl", "", aUrl, null)) {
this._logger.debug("Checking if url is flickr stream: YES: " + aUrl);
return true;
}
this._logger.debug("Checking if url is flickr stream: NO: " + aUrl);
return false;
}
flickrService.prototype.getMediaQueryFromURL =
function flickrService_getMediaQueryFromURL(aUrl, aListener)
{
var myListener = {
onResult:function (aXML) {
try {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
var userID = aXML.getElementsByTagName('user')[0].getAttribute('id');
var userName = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
results.setPropertyAsAString("query", "user:" + userID + "|username:" + userName);
results.setPropertyAsAString("title", userName);
aListener.onSuccess(results, "query");
} catch (ex) {
aListener.onError(null, "Unable to get user.", null);
}
},
onError: function (aError) {
aListener.onError(null, aError.errorString, null);
}
}
this._logger.debug("Finding User ID from Url: " + aUrl);
var params = {};
params.url = aUrl;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.urls.lookupUser", dict);
}
// END flockIMediaWebService
// Checks if the TEXTAREA is drag and droppable
flickrService.prototype._isDnDableTextarea =
function fs__isDnDableTextarea(aDocument, aXPath, aTextarea) {
if (aDocument && aXPath && aTextarea) {
var xpath = this.webDetective.getString("flickr", aXPath, "");
var results = aDocument.evaluate(xpath, aDocument, null,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
if (results && results.iterateNext() == aTextarea) {
return true;
}
}
return false;
}
// BEGIN flockIRichContentDropHandler
flickrService.prototype.handleDrop =
function flickrService_handleDrop(aFlavours, aTextarea)
{
this._logger.info(".handleDrop()");
var dropCallback = function flickr_dropCallback(aFlav) {
var data = {}, len = {};
aFlavours.getTransferData(aFlav, data, len);
var caretPos = aTextarea.selectionEnd;
var currentValue = aTextarea.value;
// Add a trailing space so that we don't mangle the url
var nextChar = currentValue.charAt(caretPos);
var trailingSpace = ((nextChar == "") ||
(nextChar == " ") ||
(nextChar == "\n"))
? ""
: " ";
// Only add a breadcrumb if the insertion point is at the end of
// the text so that we don't duplicate breadcrumbs
var breadcrumb = (aTextarea.value.length == aTextarea.selectionEnd)
? Cc[FLOCK_RDDS_CONTRACTID]
.getService(Ci.flockIRichDNDService)
.getBreadcrumb("plain")
: "";
aTextarea.value = currentValue.substring(0, caretPos)
+ data.value.QueryInterface(Ci.nsISupportsString)
.data.replace(/: /, ":\n")
+ trailingSpace
+ currentValue.substring(caretPos)
+ breadcrumb;
};
return this._handleTextareaDrop(CATEGORY_ENTRY_NAME, this.svcCoopObj.domains,
aTextarea, dropCallback);
}
// END flockIRichContentDropHandler
// ========== END flickrService class ==========
// ================================================
// ========== BEGIN XPCOM Module support ==========
// ================================================
function createModule(aParams) {
return {
registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
aParams.contractID, aFileSpec,
aLocation, aType );
var catMgr = Cc["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
if (!aParams.categories) { aParams.categories = []; }
for (var i = 0; i < aParams.categories.length; i++) {
var cat = aParams.categories[i];
catMgr.addCategoryEntry( cat.category, cat.entry,
cat.value, true, true );
}
},
getClassObject: function (aCompMgr, aCID, aIID) {
if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
return { // Factory
createInstance: function (aOuter, aIID) {
if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
var comp = new aParams.componentClass();
if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
return comp.QueryInterface(aIID);
}
};
},
canUnload: function (aCompMgr) { return true; }
};
}
// NS Module entrypoint
function NSGetModule(aCompMgr, aFileSpec) {
return createModule({
componentClass: flickrService,
CID: FLICKR_CID,
contractID: FLICKR_CONTRACTID,
componentName: CATEGORY_COMPONENT_NAME,
implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
categories: [
{ category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: FLICKR_CONTRACTID },
{ category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: FLICKR_CONTRACTID },
{ category: "flockMediaProvider", entry: CATEGORY_ENTRY_NAME, value: FLICKR_CONTRACTID },
{ category: "flockRichContentHandler", entry: CATEGORY_ENTRY_NAME, value: FLICKR_CONTRACTID }
]
});
}
// ========== END XPCOM Module support ==========
// =============================================
// ========== BEGIN MultiGetter class ==========
// =============================================
function MultiGetter() {
}
MultiGetter.prototype = {
mTimer: Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer),
init: function(aSvc, aListener, aEnumerator) {
this.mHasNew = false;
this.mNeedSave = false;
this.mSvc = aSvc;
this.mListener = aListener;
this.mArray = [];
this.mMap = {};
while (aEnumerator.hasMoreElements()) {
var p = aEnumerator.getNext();
p.QueryInterface(Components.interfaces.flockIPhotoPerson);
this.mMap[p.id] = p;
this.mArray.push(p.id);
//this._logger.info(p + " " + p.id + " " + this.mArray.length + " initting \n");
}
if (this.mSvc.getAuthPerson()) {
this.doBiggee();
}
else {
this.next();
}
},
updatePerson: function(aPerson, aPhoto) {
//this._logger.info(aPerson.username + "updating person\n");
var seq = aPerson.seq;
var newSeq = parseInt(aPhoto.id);
if (newSeq > seq) {
var oldHasNew = aPerson.hasNew;
aPerson.seq = aPhoto.id;
this.mNeedSave = true;
if (seq != 0) {
this.mHasNew = true;
aPerson.hasNew = true;
if (oldHasNew == false) {
aPerson.lastNewSeq = seq + 1;
}
}
}
this.mMap[aPerson.id] = null;// wipe this entry out
},
doBiggee: function() {
var inst = this;
var listener = {
onSearchResult: function(aEnumerator) {
//this._logger.info("on search result\n");
try {
while (aEnumerator.hasMoreElements()) {
var photo = aEnumerator.getNext();
var person = inst.mMap[photo.userid]; // username is actuall an id
//this._logger.info("result\n")
if (!person) continue;
inst.updatePerson(person, photo);
}
} catch(e) {
//this._logger.info("this" + e + " " + e.lineNumber + "\n");
}
inst.next();
},
onError: function(aError) {
//this._logger.info("on error result\n");
//hmm. mebbe should bail
inst.finish();
}
}
this.mSvc.getContactsPhotos(listener);
},
finish: function() {
//this._logger.info("FINITI\n");
if (this.mHasNew) {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_HAS_NEW);
}
else if (this.mNeedSave) {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NEED_SAVE);
}
else {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NO_CHANGE);
}
return;
},
notify: function() {
this.doNext();
},
next: function() {
this.mTimer.initWithCallback(this, 1000, 0);
},
doNext: function() {
//this._logger.info("NEXT PLEASE\n");
var inst = this;
var person = null;
for (;;) {
if (!this.mArray.length) break;
var id = this.mArray.pop();
//this._logger.info(id + " " + "< NEXT PLEASE\n");
person = this.mMap[id];
if (person) {
break;
}
}
if (!person) {
this.finish();
return;
}
var listener = {
onSearchResult: function(aEnumerator) {
//this._logger.info("b search result\n");
while (aEnumerator.hasMoreElements()) {
var photo = aEnumerator.getNext();
var person = inst.mMap[photo.userid]; // username is actuall an id
inst.updatePerson(person, photo);
break;
}
inst.next();
},
onError: function(aError) {
//this._logger.info("b search eror\n");
inst.finish();
}
}
this.mSvc.search(listener, person.id, "", "", 1, 1);
}
}
// ========== END MultiGetter class ==========
// ===========================================
// ========== BEGIN FlickrAPI class ==========
// ===========================================
function FlickrAPI() {
this._logger = Components.classes['@flock.com/logger;1'].createInstance(Components.interfaces.flockILogger);
this._logger.init('flickrAPI');
this._logger.info('Created Flickr API Object');
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.webDetective = this.acUtils.useWebDetective("flickr.xml");
this.faves_coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
var inst = this;
this.need2CreateAlbum = false;
this.api_key = gStrings["apikey"];
this.api_secret = "17b26c20558cf979";
this.endpoint = gStrings["endpoint"];
this.upload_endpoint = gStrings["uploadendpoint"];
this.auth_endpoint = gStrings["authendpoint"];
this.fakeAlbums = {};
this.realishAlbums = {};
this.req = null;
this.frob = null;
this.lastToken = new Date();
this.authUser = null;
this.filesToDelete = [];
this.setEndpoint = function(aEndpoint) {
this.endpoint = aEndpoint;
};
this.reset = function() {
this.hasCreateAlbum = null;
};
this.getAuthUser = function() {
return this.authUser;
};
this.getStoredToken = function(aListener) {
};
this.checkToken = function(aListener, aToken) {
var tokenListener = {
onResult: function (aXML) {
var flickrUser = new FlickrUser();
flickrUser.token = aXML.getElementsByTagName("token")[0].firstChild.nodeValue;
var user = aXML.getElementsByTagName("user")[0];
flickrUser.nsid = user.getAttribute("nsid");
flickrUser.id = user.getAttribute("nsid");
flickrUser.username = user.getAttribute("username");
flickrUser.fullname = user.getAttribute("fullname");
inst.authUser = flickrUser;
inst._logger.info("token checks out");
inst.lastToken = new Date();
aListener.onSuccess(null, "");
},
onError: function (aError) {
inst._logger.info("Token does not pass muster");
inst.frob = null;
aListener.onError(null);
}
}
var token = aToken;
var params = {
auth_token: token
};
this.call(tokenListener, "flickr.auth.checkToken", params);
};
this.getToken = function(aAccountURN, aListener) {
inst._logger.info("entering getToken");
var acctCoopObj = this.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
// we have an existing token, let's see if it's valid
if (acctCoopObj.authToken && acctCoopObj.authToken.length) {
var checkTokenListener = {
onSuccess : function(aSubject, aTopic) {
// the token is aiighttt lets reuse it
inst._reuseToken(aAccountURN, aListener);
},
onError: function(aError) {
// something
inst._getNewToken(aAccountURN, aListener);
}
};
this.checkToken(checkTokenListener, acctCoopObj.authToken);
} else {
this._getNewToken(aAccountURN, aListener);
}
};
this._reuseToken = function(aAccountURN, aListener) {
inst._logger.info("entering _reuseToken");
var acctCoopObj = inst.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
flickrUser.token = acctCoopObj.authToken;
flickrUser.nsid = acctCoopObj.flickr_nsid;
flickrUser.id = acctCoopObj.flickr_id;
flickrUser.username = acctCoopObj.flickr_username;
flickrUser.fullname = acctCoopObj.flickr_fullname;
this.authUser = flickrUser;
inst.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
};
this._getNewToken = function(aAccountURN, aListener, aFrob) {
inst._logger.info("entering _getNewToken");
var acctCoopObj = inst.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
var tokenListener = {
onResult: function (aXML) {
flickrUser.token = aXML.getElementsByTagName("token")[0].firstChild.nodeValue;
var user = aXML.getElementsByTagName("user")[0];
flickrUser.nsid = user.getAttribute("nsid");
flickrUser.id = user.getAttribute("nsid");
flickrUser.username = user.getAttribute("username");
flickrUser.fullname = user.getAttribute("fullname");
inst.authUser = flickrUser;
acctCoopObj.authToken = flickrUser.token;
acctCoopObj.flickr_nsid = flickrUser.nsid;
acctCoopObj.flickr_id = flickrUser.id;
acctCoopObj.flickr_username = flickrUser.username;
acctCoopObj.flickr_fullname = flickrUser.fullname;
inst.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
inst._logger.info("got token");
this.lastToken = new Date();
aListener.onSuccess();
},
onError: function (aError) {
inst._logger.info("error getting token");
this.frob = null;
if (!aError.errorCode) aError.errorCode = 1002;
aListener.onError(aError);
}
}
var frob = aFrob;
if (!frob) {
frob = this.frob;
}
var params = {
frob: frob
};
this.call(tokenListener, "flickr.auth.getToken", params);
},
this.isLoggedIn = function() {
if (this.authUser) return true;
return false;
};
this.logout = function() {
this.authUser = null;
this.frob = null;
this.token = null;
flock_refreshMediabarIfHasPrivate()
};
this.login = function(aAccountURN, aListener) {
inst._logger.info("api.login('"+aAccountURN+"')");
this.authUser = null;
this.frob = null;
var api = this;
// for http://bugzilla.flock.com/show_bug.cgi?id=6255 --
// ensure that the frob and auth token synch up
if (0 /*acctCoopObj.authToken && acctCoopObj.authToken.length*/) {
inst._logger.info("api.login('"+aAccountURN+"'): trying to reuse token");
var reuseTokenListener = {
onResult: function (aXML) {
inst._logger.info("api.login('"+aAccountURN+"') reuseTokenListener: onResult()");
aListener.onSuccess();
},
onError: function (aError) {
inst._logger.info("api.login('"+aAccountURN+"') reuseTokenListener: onError()");
aListener.onError(aError);
}
};
this.getToken(aAccountURN, reuseTokenListener);
} else {
// get new frob
inst._logger.info("api.login('"+aAccountURN+"'): need new token");
var frobListener = {
onResult: function (aXML) {
try {
var frobNode = aXML.getElementsByTagName("frob")[0];
var frob = frobNode.firstChild.nodeValue;
var authUrl = api.getAuthUrl(frob, "write");
inst.frob = frob;
api.frob = frob;
var hr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
var onReadyStateFunc = function (eEvt) {
if (hr.readyState == 4) {
if (api.webDetective.detectNoDOM("flickr", "apiAuth2", "", hr.responseText, null)) {
inst._logger.info("Successfully authorized2!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
//dump("CDC: apiAuth1: "+hr.responseText+"\n");
if (api.webDetective.detectNoDOM("flickr", "apiAuth1", "", hr.responseText, results)) {
var hr2 = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
var postBody = "magic_cookie=" + results.getPropertyAsAString("magic_cookie")
+ "&api_key=" + api.api_key
+ "&api_sig=" + results.getPropertyAsAString("api_sig")
+ "&perms=write"
+ "&frob=" + frob
+ "&done_auth=1";
hr2.onreadystatechange = function (eEvt2) {
if (hr2.readyState == 4) {
if (api.webDetective.detectNoDOM("flickr", "apiAuth2", "", hr2.responseText, null)) {
inst._logger.info("Successfully authorized!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
inst._logger.info("NOT successfully authorized!");
inst._logger.info(hr2.responseText);
aListener.onError(null);
}
}
}
hr2.backgroundRequest = true;
hr2.overrideMimeType("text/txt");
hr2.open("POST", gStrings["authendpoint"]);
hr2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
hr2.send(postBody);
} else if (api.webDetective.detectNoDOM("flickr", "apiAuth3", "", hr.responseText, null)) {
inst._logger.info("Successfully authorized with apiAuth3!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
inst._logger.debug("Error - did not detect apiAuth1 or apiAuth3");
aListener.onError(null);
}
}
}
};
hr.onreadystatechange = onReadyStateFunc;
hr.backgroundRequest = true;
hr.overrideMimeType("text/txt");
hr.open("GET", authUrl,true);
hr.send(null);
//var topWindow = windowManagerInterface.getMostRecentWindow(null);
//var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"+"url="+escape(authUrl)+"&finalString=logout.gne";
//topWindow.open(url,"_blank", "chrome,close,titlebar,resizable=yes,toolbar,dialog=no,scrollbars=yes,modal,centerscreen");
}
catch(e) {
inst._logger.info("caught this one in login: " + e);
}
},
onError: function (aError) {
inst._logger.debug("There was an error getting the frob.");
aListener.onError(aError);
}
};
this.call(frobListener, "flickr.auth.getFrob", null);
}
};
this.add2Album = function(aUploadListener, aUpload, aID) {
var inst = this;
var listener = {
onResult: function(aXML) {
inst.finalizePhoto(aUploadListener, aUpload, aID);
},
onError: function(aError) {
inst.finalizePhoto(aUploadListener, aUpload, aID);
}
}
var params = {};
params.photoset_id = aUpload.album;
params.photo_id = aID;
this.authenticatedCall(listener, "flickr.photosets.addPhoto", params);
};
this.reallyCreateAlbum =
function flickrAPI_reallyCreateAlbum(aListener, aTitle, aID) {
var myListener = {
onResult: function fAPIrCA_onResult(aXML) {
var newAlbum = Cc[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(Ci.flockIPhotoAlbum);
var photoset = aXML.getElementsByTagName("photoset")[0];
newAlbum.title = aTitle;
newAlbum.id = photoset.getAttribute("id");;
aListener.onCreateAlbumResult(newAlbum);
},
onError: function fAPIrCA_onError(aXML) {
aListener.onError(aXML);
}
}
var params = {
title: aTitle,
primary_photo_id: aID
};
this.authenticatedCall(myListener, "flickr.photosets.create", params);
};
this.finalizePhoto = function(aUploadListener, aUpload, aID) {
try {
var inst = this;
var getPhotoListener = {
onGetPhoto: function(aPhoto) {
aUploadListener.onUploadFinalized(aUpload, aPhoto);
},
onError: function(aError) {
aUploadListener.onError(null);
}
}
inst.svc.getPhoto(getPhotoListener, aID);
} catch(e) {
inst._logger.error(e);
}
};
this.mAddingAlbums = false;
this.mPhotos2Album = [];
this.processPendingAlbumAdditions = function() {
if (this.mAddingAlbums) return;
if (this.mPhotos2Album.length == 0) return;
this.mAddingAlbums = true;
var obj = this.mPhotos2Album[0];
var photoid = obj.photoid;
var albumid = obj.albumid;
var inst = this;
if (this.fakeAlbums[albumid] && !this.realishAlbums[albumid]) {
var listener = {
onCreateAlbumResult: function(aAlbum) {
inst.realishAlbums[albumid] = aAlbum.id;
inst.mAddingAlbums = false;
},
onError: function(aError) {
inst.mAddingAlbums = false;
}
}
// var params = {};
// params.photoset_id = photoid;
// params.photo_id = albumid;
var fakeAlbum = this.fakeAlbums[albumid];
this.reallyCreateAlbum(listener, fakeAlbum.title, photoid);
}
else {
if (inst.realishAlbums[albumid]) {
albumid = inst.realishAlbums[albumid];
}
var listener = {
onResult: function(aXML) {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
inst.mPhotos2Album.shift();
inst.mAddingAlbums = false;
inst.processPendingAlbumAdditions();
//re-enter to optimize
},
onError: function(aError) {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
inst.mPhotos2Album.shift();
inst.mAddingAlbums = false;
//re-enter to optimize?? this is an error condition, por
//supuesto
}
}
var params = {};
params.photoset_id = albumid;
params.photo_id = photoid;
this.authenticatedCall(listener, "flickr.photosets.addPhoto", params);
}
};
this.mCheckTicketsInProcess = false;
this.processPendingUploadTickets = function() {
if (this.mCheckTicketsInProcess) return;
var ticketList = "";
for (var p in this.mPendingTickets) {
var obj = this.mPendingTickets[p];
if (!obj) continue;//really should be removeing these - make it an array?
ticketList += obj.ticketid + ",";
}
if (ticketList.length == 0) return;
this.mCheckTicketsInProcess = true;
var params = {
tickets: ticketList
};
var inst = this;
var ticketListener = {
onResult: function (aXML) {
inst.mCheckTicketsInProcess = false;
var ticketList = aXML.getElementsByTagName("ticket");
for (var i = 0; i < ticketList.length; i++) {
var ticket = ticketList[i];
var id = ticket.getAttribute("id");
var photoid = ticket.getAttribute("photoid");
var complete = ticket.getAttribute("complete");
var invalid = ticket.getAttribute("invalid");
var obj = inst.mPendingTickets[id];
if (complete =="0") {
continue;
}
else if (invalid) {
obj.listener.onError(null);
}
else if (complete =="1") {
if (obj.upload.album && obj.upload.album.length>0) {
obj.photoid = photoid;
obj.albumid = obj.upload.album;
obj.listener = obj.listener;
inst.mPhotos2Album.push(obj);
}
else {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
}
}
else if (complete =="2") {
obj.listener.onError(null);
}
inst.mPendingTickets[id] = null;//that doesn't really remove it tho
}
},
onError: function (aXML) {
inst.mCheckTicketsInProcess = false;
}
}
this.call(ticketListener, "flickr.photos.upload.checkTickets", params);
};
this.mPendingTickets = {};
this.upload = function(aListener, aPhoto, aParams, aUpload) {
var inst = this;
this.uploader = new PhotoUploader();
var myListener = {
onResult: function(aXML) {
var rsp = aXML.getElementsByTagName("rsp")[0];
var stat = rsp.getAttribute("stat");
if (stat !="ok") {
var err = aXML.getElementsByTagName("err")[0];
var error= inst.getError('SERVICE_ERROR', aXML, null);
aListener.onError(error);
}
else {
aListener.onUploadComplete(aUpload);
var ticketid = aXML.getElementsByTagName("ticketid")[0].firstChild.nodeValue;
inst._logger.info(ticketid + "pre ticketid");
inst.mPendingTickets[ticketid] = {
ticketid: ticketid,
upload: aUpload,
listener: aListener
}
inst._logger.info(ticketid + "post ticketid");
/*
if (aUpload.album && aUpload.album.length>0) {
var ticketid = aXML.getElementsByTagName("ticketid")[0].firstChild.nodeValue;
inst.mPendingTickets[ticketid] = {
ticketid: ticketid,
upload: aUpload,
listener: aListener,
}
}
else {
aListener.onUploadFinalized(aUpload, null);
}
*/
}
},
onError: function(aErrorCode) {
if (aErrorCode) {
aListener.onError(inst.getError('HTTP_ERROR', null, aErrorCode));
} else {
aListener.onError(inst.getError('SERVICE_ERROR', null));
}
},
onProgress: function(aCurrentProgress) {
aListener.onProgress(aCurrentProgress);
}
}
this.convertBools(aParams);
this.convertTags(aParams);
aParams.auth_token = this.authUser.token;
aParams.api_key = this.api_key;
aParams = this.appendSignature(aParams);
this.uploader.setEndpoint(this.upload_endpoint);
this.uploader.upload(myListener, aPhoto, aParams);
return;
};
this.convertBools = function(aParams) {
for (var p in aParams) {
if (!p.match(/^is/)) continue;
// I hope that this doesn't break anything
if (aParams[p]=="true") aParams[p] = "1";
if (aParams[p]=="false") aParams[p] = "0";
}
};
this.convertTags = function(aParams) {
for (var p in aParams) {
if (p != "tags") continue;
var tags = aParams[p].split(",");
for (var i = 0; i < tags.length;++i) {
tags[i] = '"' + tags[i] + '"';
tags[i] = tags[i].replace(/\"+/g,'"');
}
aParams[p] = tags.join(",");
}
};
this.authenticatedCall = function(aListener, aMethod, aParams) {
if (!aParams) aParams = {};
aParams.auth_token = this.authUser.token;
this.call(aListener, aMethod, aParams);
var paramString = this.getParamString(aParams, true);
};
this.call = function(aListener, aMethod, aParams) {
this.convertBools(aParams);
this.convertTags(aParams);
if (aParams == null) aParams = [];
if (aMethod) aParams.method = aMethod;
aParams.api_key = this.api_key;
var paramString = this.getParamString(aParams, (aMethod == null));
var url = this.endpoint + "?" + paramString;
this._doCall(aListener, url, null);
};
this._doCall = function(aListener, aUrl, aContent) {
inst._logger.info("Sending " + aUrl);
this.req = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
this.req.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
this.req.open('GET', aUrl, true);
var req = this.req;
this.req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
try {
if (req.status/100 == 2) {
try {
//inst._logger.info(req.responseText);
var rsp = req.responseXML.getElementsByTagName("rsp")[0];
var stat = rsp.getAttribute("stat");
if (stat !="ok") {
var err = req.responseXML.getElementsByTagName("err")[0];
var error= inst.getError('SERVICE_ERROR', req.responseXML, null);
aListener.onError(error);
}
else {
aListener.onResult(req.responseXML);
}
} catch (ex) {
// error parsing xml
inst._logger.error(ex);
aListener.onError(inst.getError('SERVICE_ERROR', null, null));
}
}
else {
// http errors
aListener.onError(inst.getError("HTTP_ERROR", null, req.status));
}
} catch(e) {
// XMHTTPERROR (connection lost)
inst._logger.info(e);
aListener.onError(inst.getError('HTTP_ERROR',null, "9001"));
}
}
}
this.req.send(null);
};
this.getError = function(aErrorType, aXML, aHTTPErrorCode) {
var error = Components.classes[FLOCK_ERROR_CONTRACTID].createInstance(flockIError);
if (aErrorType == "HTTP_ERROR") {
error.errorCode = aHTTPErrorCode;
} else if (aErrorType == "SERVICE_ERROR") {
var errorCode;
var errorMessage;
var serviceErrorMessage;
try {
errorCode = aXML.getElementsByTagName("err")[0].getAttribute('code');
serviceErrorMessage = aXML.getElementsByTagName("err")[0].getAttribute('msg');
} catch (ex) {
errorCode = "999" // in case the error xml is invalid
}
switch (errorCode) {
case "1":
error.errorCode = error.PHOTOSERVICE_INVALID_USER;
break;
case "3":
error.errorCode = error.PHOTOSERVICE_UPLOAD_ERROR;
break;
case "4":
error.errorCode = error.PHOTOSERVICE_FILE_IS_OVER_SIZE_LIMIT;
break;
case "5":
error.errorCode = error.PHOTOSERVICE_INVALID_UPLOAD_FILE;
break;
case "6":
error.errorCode = error.PHOTOSERVICE_BANDWIDTH_REACHED;
break;
case "10":
break;
case "98":
error.errorCode = error.PHOTOSERVICE_LOGIN_FAILED;
break;
case "99":
error.errorCode = error.PHOTOSERVICE_USER_NOT_LOGGED_IN;
break;
case "100":
error.errorCode = error.PHOTOSERVICE_INVALID_API_KEY;
break;
case "105":
error.errorCode = error.PHOTOSERVICE_UNAVAILABLE;
break;
case "999":
error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
break;
default:
error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
error.serviceErrorString = serviceErrorMessage;
break;
}
}
//inst._logger.info('<<<<<<<<<<<<<<' + error.errorString + '\n');
return error;
};
this.getAuthUrl = function(aFrob, aPerms) {
var api_key = this.api_key;
var params = {
api_key: api_key,
perms: aPerms,
frob: aFrob
}
var paramString = this.getParamString(params, true);
return this.auth_endpoint + "?" + paramString;
};
this.getParamString = function(aParams, aNoMethod) {
aParams = this.appendSignature(aParams);
var rval = "";
if (!aNoMethod) rval += "method=" + aParams.method + "&";
var count = 0;
for (var p in aParams) {
if (p.match(/method/)) continue;
if (count++ != 0) rval += "&";
rval += encodeURIComponent(p) + "=" + encodeURIComponent(aParams[p]);
}
return rval;
};
this.appendSignature = function(aParams) {
var keys = [];
for (var p in aParams) {
keys.push(p);
}
keys.sort();
var preHash = this.api_secret;
for (var i = 0; i < keys.length; ++i) {
preHash += keys[i] + aParams[keys[i]];
}
inst._logger.info("preHash " + preHash);
var converter =
Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
var inputStream = converter.convertToInputStream(preHash);
aParams.api_sig = FlockCryptoHash.md5Stream(inputStream);
return aParams;
};
}
FlickrAPI.prototype = {};
// ========== END FlickrAPI class ==========
// ============================================
// ========== BEGIN FlickrUser class ==========
// ============================================
function FlickrUser() {
this.token = "";
this.perms = "";
this.nsid = "";
this.id = "";
this.username = "";
this.fullname = "";
}
FlickrUser.prototype = {};
// ========== END FlickrUser class =========
// ===============================================
// ========== BEGIN flickrAccount class ==========
// ===============================================
function flickrAccount()
{
this._logger = Components.classes['@flock.com/logger;1'].createInstance(Components.interfaces.flockILogger);
this._logger.init('flickrAccount');
this._logger.info('Created Flickr Account Object');
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.svc = Components.classes[FLICKR_CONTRACTID]
.getService(Components.interfaces.flockIMediaWebService)
.QueryInterface(Components.interfaces.flockIWebService);
if (!gFlickrAPI) {
gFlickrAPI = new FlickrAPI();
}
this.api = gFlickrAPI;
this.api.svc = this.svc;
this._coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
this.webDetective = Cc["@flock.com/web-detective;1"]
.getService(Ci.flockIWebDetective);
this._ctk = {
interfaces: [
"nsISupports",
"flockIWebServiceAccount",
"flockISocialWebServiceAccount",
"flockIMediaWebServiceAccount",
"flockIMediaUploadAccount",
"flockIFlickrAccount"
]
};
getCompTK().addAllInterfaces(this);
}
// BEGIN flockIWebServiceAccount interface
flickrAccount.prototype.urn = null;
flickrAccount.prototype.login =
function flickrAccount_login(aListener)
{
this._logger.info("{flockIWebServiceAccount}.login()");
var inst = this;
var myListener = {
onSuccess: function (aSubject, aTopic) {
inst.acUtils.ensureOnlyAuthenticatedAccount(inst.urn);
// force refresh on login
var pollerSvc = Cc["@flock.com/poller-service;1"]
.getService(Ci.flockIPollerService);
pollerSvc.forceRefresh(inst.urn);
if (aListener) {
aListener.onSuccess(null, "");
}
},
onError: function (aError) {
if (aListener) {
aListener.onError(aError);
}
}
}
this.api.logout();
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
this.api.login(this.urn, myListener);
}
flickrAccount.prototype.logout =
function flickrAccount_logout(aListener)
{
this._logger.info("{flockIWebServiceAccount}.logout()");
var acctCoopObj = this._coop.get(this.urn);
if (acctCoopObj.isAuthenticated) {
acctCoopObj.isAuthenticated = false;
this.svc.logout();
}
}
flickrAccount.prototype.activate =
function flickrAccount_activate(aListener)
{
this._logger.info("{flockIWebServiceAccount}.activate()");
var acctCoopObj = this._coop.get(this.urn);
var inst = this;
var listener = {
onSuccess: function (aSubject, aTopic) {
if (aListener) aListener.onSuccess(inst, "accountAuthorized");
acctCoopObj.isPollable = true;
inst.acUtils.ensureOnlyAuthenticatedAccount(inst.urn);
},
onError: function (aError) {
inst._logger.info( "Flickr account activation ERROR: " +
(aError ? aError.errorString : "No details. :("));
acctCoopObj.isAuthenticated = false;
}
};
this.login(listener);
// I'm going to jump the gun a bit here and assume that the authentication is
// going to succeed. If it fails, it will be caught by the listener. But at
// least this will prevent any further attempts to authenticate until this
// attempt completes.
acctCoopObj.isAuthenticated = true;
}
flickrAccount.prototype.keep =
function flickrAccount_keep()
{
this._logger.info(".keep(): "+this.urn);
var c_acct = this._coop.get(this.urn);
c_acct.isTransient = false;
this.acUtils.makeTempPasswordPermanent(this.svc.urn + ":"
+ c_acct.accountId);
// Subscribe to the recent activity RSS feed for this account
var feedMgr = Cc["@flock.com/feed-manager;1"]
.getService(Ci.flockIFeedManager);
var inst = this;
var feedListener = {
onGetFeedComplete: function keep_feed_complete(aFeed) {
feedMgr.getFeedContext("news").getRoot().subscribeFeed(aFeed);
Cc["@flock.com/metrics-service;1"]
.getService(Ci.flockIMetricsService)
.report("FeedsSidebar-AddFeed", "FlickrAccountKeep");
},
onError: function keep_feed_error(aError) {
inst._logger.debug("There was a problem subscribing to the recent "
+ "activity feed for Flickr account "
+ c_acct.accountId);
}
};
try {
var feedURI = Cc["@mozilla.org/network/standard-url;1"]
.createInstance(Ci.nsIURI);
feedURI.spec = gStrings["commentsreceivedRSS"]
.replace("%accountid%", c_acct.accountId);
feedMgr.getFeed(feedURI, feedListener);
} catch (ex) {
this._logger.debug("There was an error subscribing to the recent "
+ "activity feed for Flickr account "
+ c_acct.accountId);
}
}
// END flockIWebServiceAccount interface
// BEGIN flockISocialWebServiceAccount interface
flickrAccount.prototype.hasFriendActions = true;
flickrAccount.prototype.isStatusSupported = false;
flickrAccount.prototype.isStatusEditable = false;
flickrAccount.prototype.isPostLinkSupported = false;
flickrAccount.prototype.isMyMediaFavoritesSupported = false;
flickrAccount.prototype.setStatus =
function flickrAccount_setStatus(aStatusMessage, aListener)
{
this._logger.info("{flockISocialWebServiceAccount}.setStatus('"+aStatusMessage+"',"+
"'"+aListener+"')");
}
flickrAccount.prototype.getEditableStatus =
function flickrAccount_getEditableStatus()
{
this._logger.info("{flockISocialWebServiceAccount}.getEditableStatus()");
return "";
}
flickrAccount.prototype.formatStatusForDisplay =
function flickrAccount_formatStatusForDisplay(aStatusMessage)
{
return "";
}
flickrAccount.prototype.markAllMeNotificationsSeen =
function flickrAccount_markAllMeNotificationsSeen(aType) {
this._logger.debug(".markAllMeNotificationsSeen('" + aType + "')");
var c_acct = this._coop.get(this.urn);
switch (aType) {
case "meMessages":
c_acct.accountMessages = 0;
break;
case "meCommentActivity":
if (c_acct.flickr_comments > 0) {
c_acct.lastUpdateDate = new Date();
c_acct.flickr_comments = 0;
c_acct.flickr_comments_timespan = 0;
}
break;
default:
break;
}
}
flickrAccount.prototype.getMeNotifications =
function flickrAccount_getMeNotifications()
{
this._logger.info(".getMeNotifications()");
var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
var bundle = sbs.createBundle(FLICKR_STRING_BUNDLE);
var noties = [];
var inst = this;
function _addNotie(aType, aCount, aUrl) {
var stringName = "flock.flickr.noties."
+ aType + "."
+ ((parseInt(aCount) <= 0) ? "none" : "some");
noties.push({
class: aType,
tooltip: bundle.GetStringFromName(stringName),
metricsName: aType,
count: aCount,
URL: aUrl
});
}
var c_acct = this._coop.get(this.urn);
var url = this.webDetective.getString("flickr", "meMessages_URL", "");
_addNotie("meMessages", c_acct.accountMessages, url);
url = this.webDetective.getString("flickr", "meCommentActivity_URL", "")
.replace("%timespan%", c_acct.flickr_comments_timespan);
_addNotie("meCommentActivity", c_acct.flickr_comments, url);
return JSON.toString(noties);
}
flickrAccount.prototype.getFriendActions =
function flickrAccount_getFriendActions(aFriendURN)
{
this._logger.info(".getFriendActions('" + aFriendURN + "')");
var actionNames = ["friendMessage",
"friendViewProfile",
"friendShareFlock"];
var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
var bundle = sbs.createBundle(FLICKR_STRING_BUNDLE);
var actions = [];
var c_friend = this._coop.get(aFriendURN);
if (c_friend) {
var c_acct = this._coop.get(this.urn);
for each (var i in actionNames) {
actions.push({
label: bundle.GetStringFromName("flock.flickr.actions." + i),
class: i,
spec: this.webDetective.getString("flickr", i, "")
.replace("%accountid%", c_acct.accountId)
.replace("%friendid%", c_friend.accountId)
});
}
}
return JSON.toString(actions);
}
flickrAccount.prototype.getSharingAction =
function flickrAccount_getSharingAction(aFriendURN, aTransferable)
{
this._logger.info(".getSharingAction('" + aFriendURN + "')");
var sharingAction = "";
var c_friend = this._coop.get(aFriendURN);
if (c_friend) {
// Flavors we want to support, in order of preference
var flavors = ["text/x-flock-media",
"text/x-moz-url",
"text/unicode",
"text/html"];
var message = Cc[FLOCK_RDDS_CONTRACTID]
.getService(Ci.flockIRichDNDService)
.getMessageFromTransferable(aTransferable,
flavors.length,
flavors);
if (message.body) {
sharingAction = this.webDetective.getString("flickr", "shareAction", "")
.replace("%friendid%", c_friend.accountId);
}
}
this._logger.info("sharingAction = "+sharingAction);
return sharingAction;
}
flickrAccount.prototype.getProfileURLForFriend =
function flickrAccount_getProfileURLForFriend(aFriendURN)
{
this._logger.info(".getProfileURLForFriend('" + aFriendURN + "')");
var url = "";
var c_friend = this._coop.get(aFriendURN);
if (c_friend) {
url = this.webDetective.getString("flickr", "friendprofile", "")
.replace("%accountid%", c_friend.accountId);
}
return url;
}
flickrAccount.prototype.getPostLinkAction =
function flickrAccount_getPostLinkAction(aTransferable)
{
return "";
}
// END flockISocialWebServiceAccount interface
// BEGIN flockIFlickrAccount interface
flickrAccount.prototype.shareFlock =
function flickrAccount_shareFlock(aFriendURN)
{
this._logger.info(".shareFlock('" + aFriendURN + "')");
var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
var bundle = sbs.createBundle(FLICKR_STRING_BUNDLE);
var body = bundle.GetStringFromName("flock.flickr.friendShareFlock.message");
var subj = bundle.GetStringFromName("flock.flickr.friendShareFlock.subject");
this._composeMessage(aFriendURN, subj, body, false);
}
flickrAccount.prototype.flickrMail =
function flickrAccount_flickrMail(aFriendURN, aTransferable)
{
this._logger.info(".flickrMail('" + aFriendURN + "')");
var flavors = ["text/x-flock-media",
"text/x-moz-url",
"text/unicode",
"text/html"];
var message = Cc[FLOCK_RDDS_CONTRACTID]
.getService(Ci.flockIRichDNDService)
.getMessageFromTransferable(aTransferable,
flavors.length,
flavors);
if (message.body) {
this._composeMessage(aFriendURN, message.subject, message.body, true);
}
}
flickrAccount.prototype._composeMessage =
function flickrAccount__composeMessage(aFriendURN, aSubject, aBody, addBreadCrumb)
{
var body = aBody;
var subject = aSubject;
var c_friend = this._coop.get(aFriendURN);
var url = this.webDetective.getString("flickr", "flickrmail_URL", "")
.replace("%friendid%", c_friend.accountId);
var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
if (win) {
var browser = win.getBrowser();
var newTab = browser.loadOneTab(url, null, null, null, false, false);
var obs = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
var inst = this;
var observer = {
observe: function openSendMessageTabForFill_observer(aContent,
aTopic,
aContextUrl)
{
var contentWindow = newTab.linkedBrowser.docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
function insertContent(aWebDicString, aMessage) {
var xpathquery = inst.webDetective.getString("flickr", aWebDicString, "");
var doc = contentWindow.document;
var formItems = doc.evaluate(xpathquery, doc, null,
Ci.nsIDOMXPathResult.ANY_TYPE, null);
if (formItems) {
var formItem = formItems.iterateNext();
if (formItem.hasAttribute("value")) {
formItem.setAttribute("value", aMessage);
} else {
var textNode = doc.createTextNode(aMessage);
formItem.appendChild(textNode);
inst._logger.info("aMessage " + aMessage);
}
}
}
if (contentWindow == aContent) {
obs.removeObserver(this, "EndDocumentLoad");
insertContent("flickrmail_subjectXPath", subject);
if(addBreadCrumb)
{
// Add breadcrumb to message body
var breadcrumb = Cc[FLOCK_RDDS_CONTRACTID]
.getService(Ci.flockIRichDNDService)
.getBreadcrumb("plain");
if (breadcrumb) {
body += breadcrumb;
}
}
insertContent("flickrmail_bodyXPath", body);
}
}
};
obs.addObserver(observer, "EndDocumentLoad", false);
}
}
// END flockIFlickrAccount interface
// ========== END flickrAccount class ==========